package com.css.openapi.interceptor;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;

import com.css.common.core.constant.ApiAccess;
import com.css.common.core.exception.ServiceException;
import com.css.common.core.pojo.vo.GetQrcodeResVO;
import com.css.common.core.session.SessionManager;
import com.css.common.core.utils.GyUtils;
import com.css.common.core.utils.ResponseUtil;
import com.css.common.security.config.ApiConfig;
import com.css.openapi.entity.Ptjr;
import com.css.openapi.mapper.PtjrMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Enumeration;
import java.util.Objects;

import static com.css.common.core.enums.XtqdEnum.XTQD_XWTJR;


/**
 * @description: api访问权限拦截器
 * @Title: ApiAccessInterceptor
 * @Author xlw
 * @Package com.invoice.tcc.config.interceptor
 * @Date 2024/8/12 15:41
 */
@Slf4j
public class ApiAccessInterceptor implements HandlerInterceptor {


//    @Resource
//    private PtjrService ptjrService;
//
//    private static final String APPKEY_HEADER = "appkey";
//
//    private static final String SECRET_HEADER = "secret";
//
//    private static final String TS_HEADER = "ts";
//
//    private static final String MD5_HEADER = "md5";

    private static final String AUTHORIZATION_HEADER = "authorization";

    @Resource
    private PtjrMapper ptjrMapper;

    @Resource
    private ApiConfig apiConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断接口鉴权是否启用
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        ApiAccess apiAccess = handlerMethod.getMethodAnnotation(ApiAccess.class);
        printRequest(request);
        if (Objects.isNull(apiAccess) || apiAccess.value()) {
            return true;
        }
        log.info("apiConfig.getJqqybz():{}",apiConfig.getJqqybz());//。
        if(!apiConfig.getJqqybz()){
            log.info("清除session");
            SessionManager.getClear().setAppid("appid").setAppkey("appkey").setXtqdDm(XTQD_XWTJR.getDm());//用于测试，方便获取appid
            return true;
        }
        String authorization = request.getHeader(AUTHORIZATION_HEADER);
        LocalDateTime nowTime = LocalDateTime.now();
        GetQrcodeResVO getQrcodeResVO = new GetQrcodeResVO();
        getQrcodeResVO.setResponseTimeStamp(nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        getQrcodeResVO.setErrCode("1001");
        if (StrUtil.isBlank(authorization)) {
            getQrcodeResVO.setErrMsg("接口访问验证头authorization缺失");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("接口访问验证头authorization缺失");
        }
        String appid = "";
        String timestamp = "";
        String nonce = "";
        String signature = "";
        String authorizationStr = authorization.replaceAll("OPEN-BODY-SIG","").replaceAll(" ","").replaceAll("\"","");
        String[] authArr = authorizationStr.split(",");
        for (String str : authArr){
            if (str.startsWith("AppId=")){
                appid = str.replaceFirst("AppId=","");
            }else if(str.startsWith("Timestamp=")){
                timestamp = str.replaceFirst("Timestamp=","");
            }else if(str.startsWith("Nonce=")){
                nonce = str.replaceFirst("Nonce=","");
            } else if(str.startsWith("Signature=")){
                signature = str.replaceFirst("Signature=","");
            }
        }
        if(GyUtils.isNull(appid)){
            getQrcodeResVO.setErrMsg("接口访问验证头authorization的appid缺失");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("接口访问验证头authorization的appid缺失");
        }
        if(GyUtils.isNull(timestamp)){
            getQrcodeResVO.setErrMsg("接口访问验证头authorization的timestamp缺失");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("接口访问验证头authorization的timestamp缺失");
        }
        if(GyUtils.isNull(nonce)){
            getQrcodeResVO.setErrMsg("接口访问验证头authorization的nonce缺失");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("接口访问验证头authorization的nonce缺失");
        }
        if(GyUtils.isNull(signature)){
            getQrcodeResVO.setErrMsg("接口访问验证头authorization的signature缺失");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("接口访问验证头authorization的signature缺失");
        }
        //获取请求体
        BufferedReader reader = request.getReader();
        StringBuilder content = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            content.append(line);
        }
        String body = content.toString();
        //获取appkey
        Ptjr ptjr = new LambdaQueryChainWrapper<>(ptjrMapper)
                .select(Ptjr::getAppkey)
                .eq(Ptjr::getGsuuid, appid)
                .eq(Ptjr::getScbj,"0")
                .last(" limit 1")
                .one();
        if (Objects.isNull(ptjr)) {
            getQrcodeResVO.setErrMsg("appid："+appid +"，未获取到对应appkey");
            ResponseUtil.out(response, getQrcodeResVO);
            throw new ServiceException("tcc_ptjr找不到appid："+appid +"对应的记录！");
        }
        //加签
        byte[] data = body.getBytes("utf-8");
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid + timestamp + nonce + testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(ptjr.getAppkey().getBytes("utf-8"), "HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes("utf-8"));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        //验签
        if (Objects.equals(signature, localSignatureStr)) {
            log.info("验签清除session");
            SessionManager.getClear().setAppid(appid).setAppkey(ptjr.getAppkey()).setXtqdDm(XTQD_XWTJR.getDm());
            return true;
        }
        getQrcodeResVO.setErrMsg("接口访问验证失败");
        ResponseUtil.out(response, getQrcodeResVO);
        throw new ServiceException("接口访问验证失败");
    }

    private void printRequest(HttpServletRequest request){
        String header = "";
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            header = header+headerName+":"+headerValue+"&";
        }
        log.info("请求路径：{}，请求类型：{}，请求头：{}",request.getRequestURL().toString(),request.getMethod(),header);
    }
}
